package org.ninjarope.cinderstained.main.screens;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

import org.ninjarope.cinderstained.main.engine.Game;
import org.ninjarope.cinderstained.main.engine.PlayerData;
import org.ninjarope.cinderstained.main.engine.Screen;
import org.ninjarope.cinderstained.main.engine.map.GameMap;
import org.ninjarope.cinderstained.main.engine.menu.MenuAction;
import org.ninjarope.cinderstained.main.engine.menu.MenuItem;
import org.ninjarope.cinderstained.main.gameplay.Creep;
import org.ninjarope.cinderstained.main.gameplay.Summon;
import org.ninjarope.cinderstained.main.gameplay.definition.GameActor;
import org.ninjarope.cinderstained.main.gameplay.definition.pool.implement.CreepPool;
import org.ninjarope.cinderstained.main.gameplay.definition.pool.implement.DamagePool;
import org.ninjarope.cinderstained.main.gameplay.definition.pool.implement.SummonPool;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GLCommon;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.CircleShape;

public class TestingStuff extends Screen {

	protected ArrayList<Creep> creeps;
	public static ArrayList<Summon> summons;
	public static GameMap map;
	public static CreepPool creepPool;
	public static SummonPool summonPool;
	protected DamagePool dp;
	protected PlayerData player;
	protected boolean menuActive;
	protected MenuItem menu;
	// rendering objects sorted by y and x cordinates
	public static ArrayList<GameActor> renderList;

	// if set to true screen will display data such as waypoints, time to next
	// attack, tower range
	// and allow waypoint editing
	// TODO implement debug mode
	protected boolean debugMode;
	// odbrajava vreme do sledeceg spawn-a
	// TODO prebaciti u mapu
	protected float spawnTimer = 0;
	protected int respawnTime;

	// TODO prebaciti u zasebnu klasu sa podacima o talasu
	// ili cuvati podatak o vremenu spanovanja dva creepa iste vrste u samom
	// creepu
	public TestingStuff() {
		super();
		debugMode = true;
		menuActive = false;
		map = new GameMap();
		Game.get().addAtlas("world", "data/sprites1.txt");
		/*
		 * TowerScriptParser t = new TowerScriptParser(); try { t.execute(map,
		 * "data/test.txt"); } catch (IOException e) { e.printStackTrace(); }
		 */
		creeps = new ArrayList<Creep>();
		summons = new ArrayList<Summon>();
		renderList = new ArrayList<GameActor>();

		respawnTime = 3;
		spawnTimer = respawnTime;
		creepPool = (CreepPool) Game.get().getPool("creeps");
		dp = (DamagePool) Game.get().getPool("damage");
		summonPool = (SummonPool) Game.get().getPool("summons");

		menu = new MenuItem();
		menu.define("world:waypoint");
		menu.title = "menu";
		MenuItem temp = new MenuItem();
		temp.define("world:waypoint");
		temp.title = "towers";
		temp.action = MenuAction.TOWER;
		temp.root = menu;
		menu.items.add(temp);

		MenuItem temp1 = new MenuItem();
		temp1.define("world:waypoint");
		temp1.title = "waypoints";
		temp1.action = MenuAction.WAYPOINT;
		temp1.root = menu;
		menu.items.add(temp1);
		System.out.println("menu has " + menu.items.size() + " submeni");

		player = new PlayerData();
		player.life = 100;
		player.money = 1000;
		player.score = 0;

	}

	@Override
	public void update(float deltaTime) {
		if (Gdx.input.justTouched()) {
			guiCamera.unproject(touchPoint.set(Gdx.input.getX(),
					Gdx.input.getY(), 0));
			if (!menuActive) {
				menuActive = true;
				menu.active = true;
				menu.moveTo(touchPoint.x, touchPoint.y, guiCamera);
			} else {
				menuActive = menu.isHit(touchPoint.x, touchPoint.y);
			}

			/*
			 * guiCamera.unproject(touchPoint.set(Gdx.input.getX(),
			 * Gdx.input.getY(), 0)); // dodavanje novog waypoint-a if
			 * (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
			 * map.waypoints.add(new Vector2(touchPoint.x, touchPoint.y)); }
			 * else if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) { Summon
			 * summonTemp = summonPool.request();
			 * summonTemp.define("world:you"); summonTemp.attackSpeed.current =
			 * 1; summonTemp.range.current = 150; summonTemp.dmg.current = 2;
			 * summonTemp.moveTo(touchPoint.x, touchPoint.y);
			 * summons.add(summonTemp); renderList.add(summonTemp); }
			 */
		}

		// spanovanje novog creepa ikoliko je isteklo vreme
		spawnTimer -= deltaTime;
		if (spawnTimer < 0) {
			Creep temp = creepPool.request();
			temp.define("world:enemy");
			temp.health.current = 10;
			temp.nextWaypoint = 0;
			temp.waypoints = this.map.waypoints;
			creeps.add(temp);
			renderList.add(temp);
			// reset timera
			spawnTimer = respawnTime;
		}
		// TODO uradeti proveru ukoliko je creep odsetao sa mape i unistiti ga
		// uz smanjenje igracevog hp-a

		// podesavanje vremena kula do sledeceg napada
		// ukoliko je vreme za sledeci napad vece od nule znaci da je kula
		// napala ranije i da ceka sledeci napad
		for (Summon s : summons) {
			if (s.nextAttack > 0)
				s.nextAttack -= deltaTime;
		}

		// FIXME
		for (Iterator<Creep> it = creeps.iterator(); it.hasNext();) {
			Creep a = it.next();
			a.calculateMove(deltaTime);
			//ukoliko je creep izasao sa mape
			if (a.position.x > guiCamera.viewportWidth) {
				player.life--;
				creepPool.release(a);
				renderList.remove(a);
				it.remove();
			} else {
				
				for (Summon s : summons) {
					// System.out.println(a.position.dst(s.position));
					if (a.position.dst(s.position) < s.range.current
							&& !(s.nextAttack > 0)) {

						a.onAttack(s.dmg);
						s.nextAttack = s.attackSpeed.current;

						// ukoliko je creep umro
						if (a.health.current <= 0) {
							// provera da li se creep uklanja iz niza ili je
							// morfovao
							if (a.onDeath()) {
								player.score++;
								creepPool.release(a);
								renderList.remove(a);
								it.remove();
							}
						}
					}
				}
			}
		}
		Collections.sort(renderList);
	}

	@Override
	public void present(float deltaTime) {
		GLCommon gl = Gdx.gl;
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		guiCamera.update();
		batch.setProjectionMatrix(guiCamera.combined);
		batch.begin();

		if (debugMode) {
			// ispis kordinata
			String cord = "";
			cord = cord + Float.toString(touchPoint.x) + ", "
					+ Float.toString(touchPoint.y);

			font.draw(batch, cord, 10, guiCamera.viewportHeight);

			// if game is running in debug mode
			// draw waypoints

			for (Vector2 v : map.waypoints) {
				TextureRegion reg = Game.get()
						.getFromAtlas("world", "waypoint");
				batch.draw(reg, v.x, v.y, 15, 15);
			}

			for (Creep v : creeps) {
				font.draw(batch, Integer.toString(v.health.current),
						(int) v.bounds.x, v.bounds.y);
			}

			for (Summon v : summons) {
				// drawing tower range if game is running in debug mode

				TextureRegion reg = Game.get().getFromAtlas("world", "range");
				batch.draw(reg, v.position.x - v.range.current, v.position.y
						- v.range.current, v.range.current * 2,
						v.range.current * 2);
				// drawing sprite rectangle border
				reg = Game.get().getFromAtlas("world", "waypoint");
				batch.draw(reg, v.bounds.x, v.bounds.y, 15, 15);
				batch.draw(reg, v.bounds.x + v.bounds.width, v.bounds.y
						+ v.bounds.height, 15, 15);
				batch.draw(reg, v.position.x, v.position.y, 15, 15);

				font.draw(batch, Float.toString(v.nextAttack),
						(int) v.bounds.x, v.bounds.y);

			}
		}
		// drawing objects
		for (GameActor a : renderList) {
			a.render(batch);
		}

		if (menuActive) {
			menu.render(batch, font);
		}

		// drawing gui data
		font.draw(batch, "Life: " + player.life, guiCamera.viewportWidth - 100,
				guiCamera.viewportHeight);
		
		font.draw(batch, "Score: " + player.score, guiCamera.viewportWidth - 200,
				guiCamera.viewportHeight);

		font.draw(batch, "Money: " + player.money, guiCamera.viewportWidth - 350,
				guiCamera.viewportHeight);
		
		batch.end();
	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub

	}

	@Override
	public void resume() {
		// TODO Auto-generated method stub

	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub

	}

	public static Vector2 normalize(Vector2 value) {
		Vector2 vector = new Vector2();
		float num = (value.x * value.x) + (value.y * value.y);
		float num2 = 1f / ((float) Math.sqrt((double) num));
		vector.x = value.x * num2;
		vector.y = value.y * num2;
		return vector;
	}

	/**
	 * Method for creating circles
	 * 
	 * @param world
	 * @param x
	 * @param y
	 * @param radius
	 * @param isStatic
	 * @return
	 */
	public static CircleShape createCircle(float x, float y, float radius) {
		CircleShape sd = new CircleShape();
		sd.setRadius(radius);

		return sd;
	}

}
